home *** CD-ROM | disk | FTP | other *** search
Text File | 1995-03-27 | 49.1 KB | 1,103 lines | [TEXT/ROSA] |
- Common Lisp the Language, 2nd Edition
- -------------------------------------------------------------------------------
-
- 8. Macros
-
- The Common Lisp macro facility allows the user to define arbitrary functions
- that convert certain Lisp forms into different forms before evaluating or
- compiling them. This is done at the expression level, not at the
- character-string level as in most other languages. Macros are important in the
- writing of good code: they make it possible to write code that is clear and
- elegant at the user level but that is converted to a more complex or more
- efficient internal form for execution.
-
- When eval is given a list whose car is a symbol, it looks for local definitions
- of that symbol (by flet, labels, and macrolet); if that fails, it looks for a
- global definition. If the definition is a macro definition, then the original
- list is said to be a macro call. Associated with the definition will be a
- function of two arguments, called the expansion function. This function is
- called with the entire macro call as its first argument (the second argument is
- a lexical environment); it must return some new Lisp form, called the expansion
- of the macro call. (Actually, a more general mechanism is involved; see
- macroexpand.) This expansion is then evaluated in place of the original form.
-
- When a function is being compiled, any macros it contains are expanded at
- compilation time. This means that a macro definition must be seen by the
- compiler before the first use of the macro.
-
- More generally, an implementation of Common Lisp has great latitude in deciding
- exactly when to expand macro calls within a program. For example, it is
- acceptable for the defun special form to expand all macro calls within its body
- at the time the defun form is executed and record the fully expanded body as
- the body of the function being defined. (An implementation might even choose
- always to compile functions defined by defun, even when operating in an
- ``interpretive'' mode.)
-
- Macros should be written so as to depend as little as possible on the execution
- environment to produce a correct expansion. To ensure consistent behavior, it
- is best to ensure that all macro definitions are available, whether to the
- interpreter or compiler, before any code containing calls to those macros is
- introduced.
-
- In Common Lisp, macros are not functions. In particular, macros cannot be used
- as functional arguments to such functions as apply, funcall, or map; in such
- situations, the list representing the ``original macro call'' does not exist,
- and cannot exist, because in some sense the arguments have already been
- evaluated.
-
- -------------------------------------------------------------------------------
-
- * Macro Definition
- * Macro Expansion
- * Destructuring
- * Compiler Macros
- * Environments
-
- -------------------------------------------------------------------------------
-
- 8.1. Macro Definition
-
- The function macro-function determines whether a given symbol is the name of a
- macro. The defmacro construct provides a convenient way to define new macros.
-
- [old_change_begin]
-
- [Function]
- macro-function symbol
-
- The argument must be a symbol. If the symbol has a global function definition
- that is a macro definition, then the expansion function (a function of two
- arguments, the macro-call form and an environment) is returned. If the symbol
- has no global function definition, or has a definition as an ordinary function
- or as a special form but not as a macro, then nil is returned. The function
- macroexpand is the best way to invoke the expansion function.
-
- It is possible for both macro-function and special-form-p to be true of a
- symbol. This is possible because an implementation is permitted to implement
- any macro also as a special form for speed. On the other hand, the macro
- definition must be available for use by programs that understand only the
- standard special forms listed in table 5-1.
-
- macro-function cannot be used to determine whether a symbol names a locally
- defined macro established by macrolet; macro-function can examine only global
- definitions.
-
- setf may be used with macro-function to install a macro as a symbol's global
- function definition:
-
- (setf (macro-function symbol) fn)
-
- The value installed must be a function that accepts two arguments, an entire
- macro call and an environment, and computes the expansion for that call.
- Performing this operation causes the symbol to have only that macro definition
- as its global function definition; any previous definition, whether as a macro
- or as a function, is lost. It is an error to attempt to redefine the name of a
- special form.
- [old_change_end]
-
- [change_begin]
- X3J13 voted in March 1988 (MACRO-FUNCTION-ENVIRONMENT) to add an optional
- environment argument to macro-function.
-
- [Function]
- macro-function symbol &optional env
-
- The first argument must be a symbol. If the symbol has a function definition
- that is a macro definition, whether a local one established in the environment
- env by macrolet or a global one established as if by defmacro, then the
- expansion function (a function of two arguments, the macro-call form and an
- environment) is returned. If the symbol has no function definition, or has a
- definition as an ordinary function or as a special form but not as a macro,
- then nil is returned. The function macroexpand or macroexpand-1 is the best way
- to invoke the expansion function.
-
- It is possible for both macro-function and special-form-p to be true of a
- symbol. This is possible because an implementation is permitted to implement
- any macro also as a special form for speed. On the other hand, the macro
- definition must be available for use by programs that understand only the
- standard special forms listed in table 5-1.
-
- setf may be used with macro-function to install a macro as a symbol's global
- function definition:
-
- (setf (macro-function symbol) fn)
-
- The value installed must be a function that accepts two arguments, an entire
- macro call and an environment, and computes the expansion for that call.
- Performing this operation causes the symbol to have only that macro definition
- as its global function definition; any previous definition, whether as a macro
- or as a function, is lost. One cannot use setf to establish a local macro
- definition; it is an error to supply a second argument to macro-function when
- using it with setf. It is an error to attempt to redefine the name of a special
- form.
-
- See also compiler-macro-function.
- [change_end]
-
- [Macro]
-
- defmacro name lambda-list [[ {declaration}* | doc-string ]] {form}*
-
- defmacro is a macro-defining macro that arranges to decompose the macro-call
- form in an elegant and useful way. defmacro has essentially the same syntax as
- defun: name is the symbol whose macro definition we are creating, lambda-list
- is similar in form to a lambda-list, and the forms constitute the body of the
- expander function. The defmacro construct arranges to install this expander
- function, as the global macro definition of name.
-
- [old_change_begin]
- The expander function is effectively defined in the global environment;
- lexically scoped entities established outside the defmacro form that would
- ordinarily be lexically apparent are not visible within the body of the
- expansion function.
- [old_change_end]
-
- [change_begin]
- X3J13 voted in March 1989 (DEFINING-MACROS-NON-TOP-LEVEL) to clarify that,
- while defining forms normally appear at top level, it is meaningful to place
- them in non-top-level contexts. Furthermore, defmacro should define the
- expander function within the enclosing lexical environment, not within the
- global environment.
-
- X3J13 voted in March 1988 (FLET-IMPLICIT-BLOCK) to specify that the body of
- the expander function defined by defmacro is implicitly enclosed in a block
- construct whose name is the same as the name of the defined macro. Therefore
- return-from may be used to exit from the function.
- [change_end]
-
- The name is returned as the value of the defmacro form.
-
- If we view the macro call as a list containing a function name and some
- argument forms, in effect the expander function and the list of (unevaluated)
- argument forms is given to apply. The parameter specifiers are processed as for
- any lambda-expression, using the macro-call argument forms as the arguments.
- Then the body forms are evaluated as an implicit progn, and the value of the
- last form is returned as the expansion of the macro call.
-
- If the optional documentation string doc-string is present (if not followed by
- a declaration, it may be present only if at least one form is also specified,
- as it is otherwise taken to be a form), then it is attached to the name as a
- documentation string of type function; see documentation.
-
- [old_change_begin]
- Like the lambda-list in a defun, a defmacro lambda-list may contain the
- lambda-list keywords &optional, &rest, &key, &allow-other-keys, and &aux. For
- &optional and &key parameters, initialization forms and supplied-p parameters
- may be specified, just as for defun. Three additional markers are allowed in
- defmacro variable lists only.
- [old_change_end]
-
- [change_begin]
- These three markers are now allowed in other constructs as well.
- [change_end]
-
- &body
- This is identical in function to &rest, but it informs certain
- output-formatting and editing functions that the remainder of the form is
- treated as a body and should be indented accordingly. (Only one of &body
- or &rest may be used.)
-
- &whole
- This is followed by a single variable that is bound to the entire
- macro-call form; this is the value that the macro definition function
- receives as its single argument. &whole and the following variable should
- appear first in the lambda-list, before any other parameter or lambda-list
- keyword.
-
- &environment
- This is followed by a single variable that is bound to an environment
- representing the lexical environment in which the macro call is to be
- interpreted. This environment may not be the complete lexical environment;
- it should be used only with the function macroexpand for the sake of any
- local macro definitions that the macrolet construct may have established
- within that lexical environment. This is useful primarily in the rare
- cases where a macro definition must explicitly expand any macros in a
- subform of the macro call before computing its own expansion.
-
- See lambda-list-keywords.
-
- [change_begin]
- Notice of correction. In the first edition, the symbol &environment at the left
- margin above was inadvertently omitted.
-
- X3J13 voted in March 1989 (MACRO-ENVIRONMENT-EXTENT) to specify that macro
- environment objects received with the &environment argument of a macro function
- have only dynamic extent. The consequences are undefined if such objects are
- referred to outside the dynamic extent of that particular invocation of the
- macro function. This allows implementations to use somewhat more efficient
- techniques for representing environment objects.
-
- X3J13 voted in March 1989 (DEFMACRO-LAMBDA-LIST) to clarify the permitted
- uses of &body, &whole, and &environment:
-
- * &body may appear at any level of a defmacro lambda-list.
-
- * &whole may appear at any level of a defmacro lambda-list. At inner levels
- a &whole variable is bound to that part of the argument that matches the
- sub-lambda-list in which &whole appears. No matter where &whole is used,
- other parameters or lambda-list keywords may follow it.
-
- * &environment may occur only at the outermost level of a defmacro
- lambda-list, and it may occur at most once, but it may occur anywhere
- within that lambda-list, even before an occurrence of &whole.
-
- [change_end]
-
- defmacro, unlike any other Common Lisp construct that has a lambda-list as part
- of its syntax, provides an additional facility known as destructuring.
-
- [change_begin]
- See destructuring-bind, which provides the destructuring facility separately.
- [change_end]
-
- Anywhere in the lambda-list where a parameter name may appear, and where
- ordinary lambda-list syntax (as described in section 5.2.2) does not otherwise
- allow a list, a lambda-list may appear in place of the parameter name. When
- this is done, then the argument form that would match the parameter is treated
- as a (possibly dotted) list, to be used as an argument forms list for
- satisfying the parameters in the embedded lambda-list. As an example, one could
- write the macro definition for dolist in this manner:
-
- (defmacro dolist ((var listform &optional resultform)
- &rest body)
- ...)
-
- More examples of embedded lambda-lists in defmacro are shown below.
-
- Another destructuring rule is that defmacro allows any lambda-list (whether
- top-level or embedded) to be dotted, ending in a parameter name. This situation
- is treated exactly as if the parameter name that ends the list had appeared
- preceded by &rest. For example, the definition skeleton for dolist shown above
- could instead have been written
-
- (defmacro dolist ((var listform &optional resultform)
- . body)
- ...)
-
- If the compiler encounters a defmacro, the new macro is added to the
- compilation environment, and a compiled form of the expansion function is also
- added to the output file so that the new macro will be operative at run time.
- If this is not the desired effect, the defmacro form can be wrapped in an
- eval-when construct.
-
- It is permissible to use defmacro to redefine a macro (for example, to install
- a corrected version of an incorrect definition), or to redefine a function as a
- macro. It is an error to attempt to redefine the name of a special form (see
- table 5-1) as a macro. See macrolet, which establishes macro definitions over a
- restricted lexical scope.
-
- [change_begin]
- See also define-compiler-macro.
- [change_end]
-
- Suppose, for the sake of example, that it were desirable to implement a
- conditional construct analogous to the Fortran arithmetic IF statement. (This
- of course requires a certain stretching of the imagination and suspension of
- disbelief.) The construct should accept four forms: a test-value, a neg-form, a
- zero-form, and a pos-form. One of the last three forms is chosen to be executed
- according to whether the value of the test-form is positive, negative, or zero.
- Using defmacro, a definition for such a construct might look like this:
-
- (defmacro arithmetic-if (test neg-form zero-form pos-form)
- (let ((var (gensym)))
- `(let ((,var ,test))
- (cond ((< ,var 0) ,neg-form)
- ((= ,var 0) ,zero-form)
- (t ,pos-form)))))
-
- Note the use of the backquote facility in this definition (see section 22.1.3).
- Also note the use of gensym to generate a new variable name. This is necessary
- to avoid conflict with any variables that might be referred to in neg-form,
- zero-form, or pos-form.
-
- If the form is executed by the interpreter, it will cause the function
- definition of the symbol arithmetic-if to be a macro associated with which is a
- two-argument expansion function roughly equivalent to
-
- (lambda (calling-form environment)
- (declare (ignore environment))
- (let ((var (gensym)))
- (list 'let
- (list (list 'var (cadr calling-form)))
- (list 'cond
- (list (list '< var '0) (caddr calling-form))
- (list (list '= var '0) (cadddr calling-form))
- (list 't (fifth calling-form))))))
-
- The lambda-expression is produced by the defmacro declaration. The calls to
- list are the (hypothetical) result of the backquote (`) macro character and its
- associated commas. The precise macro expansion function may depend on the
- implementation, for example providing some degree of explicit error checking on
- the number of argument forms in the macro call.
-
- Now, if eval encounters
-
- (arithmetic-if (- x 4.0)
- (- x)
- (error "Strange zero")
- x)
-
- this will be expanded into something like
-
- (let ((g407 (- x 4.0)))
- (cond ((< g407 0) (- x))
- ((= g407 0) (error "Strange zero"))
- (t x)))
-
- and eval tries again on this new form. (It should be clear now that the
- backquote facility is very useful in writing macros, since the form to be
- returned is normally a complex list structure, typically consisting of a mostly
- constant template with a few evaluated forms here and there. The backquote
- template provides a ``picture'' of the resulting code, with places to be filled
- in indicated by preceding commas.)
-
- To expand on this example, stretching credibility to its limit, we might allow
- the pos-form and zero-form to be omitted, allowing their values to default to
- nil, in much the same way that the else form of a Common Lisp if construct may
- be omitted:
-
- (defmacro arithmetic-if (test neg-form
- &optional zero-form pos-form)
- (let ((var (gensym)))
- `(let ((,var ,test))
- (cond ((< ,var 0) ,neg-form)
- ((= ,var 0) ,zero-form)
- (t ,pos-form)))))
-
- Then one could write
-
- (arithmetic-if (- x 4.0) (print x))
-
- which would be expanded into something like
-
- (let ((g408 (- x 4.0)))
- (cond ((< g408 0) (print x))
- ((= g408 0) nil)
- (t nil)))
-
- The resulting code is correct but rather silly-looking. One might rewrite the
- macro definition to produce better code when pos-form and possibly zero-form
- are omitted, or one might simply rely on the Common Lisp implementation to
- provide a compiler smart enough to improve the code itself.
-
- Destructuring is a very powerful facility that allows the defmacro lambda-list
- to express the structure of a complicated macro-call syntax. If no lambda-list
- keywords appear, then the defmacro lambda-list is simply a list, nested to some
- extent, containing parameter names at the leaves. The macro-call form must have
- the same list structure. For example, consider this macro definition:
-
- (defmacro halibut ((mouth eye1 eye2)
- ((fin1 length1) (fin2 length2))
- tail)
- ...)
-
- Now consider this macro call:
-
- (halibut (m (car eyes) (cdr eyes))
- ((f1 (count-scales f1)) (f2 (count-scales f2)))
- my-favorite-tail)
-
- This would cause the expansion function to receive the following values for its
- parameters:
-
- Parameter Value
- ---------------------------------
- mouth m
- eye1 (car eyes)
- eye2 (cdr eyes)
- fin1 f1
- length1 (count-scales f1)
- fin2 f2
- length2 (count-scales f2)
- tail my-favorite-tail
- ---------------------------------
-
- The following macro call would be in error because there would be no argument
- form to match the parameter length1:
-
- (halibut (m (car eyes) (cdr eyes))
- ((f1) (f2 (count-scales f2)))
- my-favorite-tail)
-
- The following macro call would be in error because a symbol appears in the call
- where the structure of the lambda-list requires a list.
-
- (halibut my-favorite-head
- ((f1 (count-scales f1)) (f2 (count-scales f2)))
- my-favorite-tail)
-
- The fact that the value of the variable my-favorite-head might happen to be a
- list is irrelevant here. It is the macro call itself whose structure must match
- that of the defmacro lambda-list.
-
- The use of lambda-list keywords adds even greater flexibility. For example,
- suppose it is convenient within the expansion function for halibut to be able
- to refer to the list whose components are called mouth, eye1, and eye2 as head.
- One may write this:
-
- (defmacro halibut ((&whole head mouth eye1 eye2)
- ((fin1 length1) (fin2 length2))
- tail)
-
- Now consider the same valid macro call as before:
-
- (halibut (m (car eyes) (cdr eyes))
- ((f1 (count-scales f1)) (f2 (count-scales f2)))
- my-favorite-tail)
-
- This would cause the expansion function to receive the same values for its
- parameters and also a value for the parameter head:
-
- Parameter Value
- ------------------------------------------
- head (m (car eyes) (cdr eyes))
- ------------------------------------------
-
- The stipulation that an embedded lambda-list is permitted only where ordinary
- lambda-list syntax would permit a parameter name but not a list is made to
- prevent ambiguity. For example, one may not write
-
- (defmacro loser (x &optional (a b &rest c) &rest z)
- ...)
-
- because ordinary lambda-list syntax does permit a list following &optional; the
- list (a b &rest c) would be interpreted as describing an optional parameter
- named a whose default value is that of the form b, with a supplied-p parameter
- named &rest (not legal), and an extraneous symbol c in the list (also not
- legal). An almost correct way to express this is
-
- (defmacro loser (x &optional ((a b &rest c)) &rest z)
- ...)
-
- The extra set of parentheses removes the ambiguity. However, the definition is
- now incorrect because a macro call such as (loser (car pool)) would not provide
- any argument form for the lambda-list (a b &rest c), and so the default value
- against which to match the lambda-list would be nil because no explicit default
- value was specified. This is in error because nil is an empty list; it does not
- have forms to satisfy the parameters a and b. The fully correct definition
- would be either
-
- (defmacro loser (x &optional ((a b &rest c) '(nil nil)) &rest z)
- ...)
-
- or
-
- (defmacro loser (x &optional ((&optional a b &rest c)) &rest z)
- ...)
-
- These differ slightly: the first requires that if the macro call specifies a
- explicitly then it must also specify b explicitly, whereas the second does not
- have this requirement. For example,
-
- (loser (car pool) ((+ x 1)))
-
- would be a valid call for the second definition but not for the first.
-
- -------------------------------------------------------------------------------
-
- 8.2. Macro Expansion
-
- The macroexpand function is the conventional means for expanding a macro call.
- A hook is provided for a user function to gain control during the expansion
- process.
-
- [Function]
- macroexpand form &optional env
- macroexpand-1 form &optional env
-
- If form is a macro call, then macroexpand-1 will expand the macro call once and
- return two values: the expansion and t. If form is not a macro call, then the
- two values form and nil are returned.
-
- A form is considered to be a macro call only if it is a cons whose car is a
- symbol that names a macro. The environment env is similar to that used within
- the evaluator (see evalhook); it defaults to a null environment. Any local
- macro definitions established within env by macrolet will be considered. If
- only form is given as an argument, then the environment is effectively null,
- and only global macro definitions (as established by defmacro) will be
- considered.
-
- Macro expansion is carried out as follows. Once macroexpand-1 has determined
- that a symbol names a macro, it obtains the expansion function for that macro.
- The value of the variable *macroexpand-hook* is then called as a function of
- three arguments: the expansion function, the form, and the environment env. The
- value returned from this call is taken to be the expansion of the macro call.
- The initial value of *macroexpand-hook* is funcall, and the net effect is to
- invoke the expansion function, giving it form and env as its two arguments.
-
- [change_begin]
- X3J13 voted in June 1988 (FUNCTION-TYPE) to specify that the value of
- *macroexpand-hook* is first coerced to a function before being called as the
- expansion interface hook. Therefore its value may be a symbol, a
- lambda-expression, or any object of type function.
-
- X3J13 voted in March 1989 (MACRO-ENVIRONMENT-EXTENT) to specify that macro
- environment objects received by a *macroexpand-hook* function have only dynamic
- extent. The consequences are undefined if such objects are referred to outside
- the dynamic extent of that particular invocation of the hook function. This
- allows implementations to use somewhat more efficient techniques for
- representing environment objects.
- [change_end]
-
- [old_change_begin]
- (The purpose of *macroexpand-hook* is to facilitate various techniques for
- improving interpretation speed by caching macro expansions.)
- [old_change_end]
-
- [change_begin]
- X3J13 voted in June 1989 (MACRO-CACHING) to clarify that, while
- *macroexpand-hook* may be useful for debugging purposes, despite the original
- design intent there is currently no correct portable way to use it for caching
- macro expansions.
-
- * Caching by displacement (performing a side effect on the macro-call form)
- won't work because the same (eq) macro-call form may appear in distinct
- lexical contexts. In addition, the macro-call form may be a read-only
- constant (see quote and also section 25.1).
-
- * Caching by table lookup won't work because such a table would have to be
- keyed by both the macro-call form and the environment, but X3J13 voted in
- March 1989 (MACRO-ENVIRONMENT-EXTENT) to permit macro environments to
- have only dynamic extent.
-
- * Caching by storing macro-call forms and expansions within the environment
- object itself would work, but there are no portable primitives that would
- allow users to do this.
-
- X3J13 also noted that, although there seems to be no correct portable way to
- use *macroexpand-hook* to cache macro expansions, there is no requirement that
- an implementation call the macro expansion function more than once for a given
- form and lexical environment.
-
- X3J13 voted in March 1989 (SYMBOL-MACROLET-SEMANTICS) to specify that
- macroexpand-1 will also expand symbol macros defined by symbol-macrolet;
- therefore a form may also be a macro call if it is a symbol. The vote did not
- address the interaction of this feature with the *macroexpand-hook* function.
- An obvious implementation choice is that the hook function is indeed called and
- given a special expansion function that, when applied to the form (a symbol)
- and env, will produce the expansion, just as for an ordinary macro; but this is
- only my suggestion.
- [change_end]
-
- The evaluator expands macro calls as if through the use of macroexpand-1; the
- point is that eval also uses *macroexpand-hook*.
-
- macroexpand is similar to macroexpand-1, but repeatedly expands form until it
- is no longer a macro call. (In effect, macroexpand simply calls macroexpand-1
- repeatedly until the second value returned is nil.) A second value of t or nil
- is returned as for macroexpand-1, indicating whether the original form was a
- macro call.
-
- [Variable]
- *macroexpand-hook*
-
- The value of *macroexpand-hook* is used as the expansion interface hook by
- macroexpand-1.
-
- -------------------------------------------------------------------------------
-
- 8.3. Destructuring
-
- [change_begin]
- X3J13 voted in March 1989 (DESTRUCTURING-BIND) to make the destructuring
- feature of defmacro available as a separate facility.
-
- [Macro]
-
- destructuring-bind lambda-list expression {declaration}* {form}*
-
- This macro binds the variables specified in lambda-list to the corresponding
- values in the tree structure resulting from evaluating the expression, then
- executes the forms as an implicit progn.
-
- A destructuring-bind lambda-list may contain the lambda-list keywords
- &optional, &rest, &key, &allow-other-keys, and &aux; &body and &whole may also
- be used as they are in defmacro, but &environment may not be used. Nested and
- dotted lambda-lists are also permitted as for defmacro. The idea is that a
- destructuring-bind lambda-list has the same format as inner levels of a
- defmacro lambda-list.
-
- If the result of evaluating the expression does not match the destructuring
- pattern, an error should be signaled.
- [change_end]
-
- -------------------------------------------------------------------------------
-
- 8.4. Compiler Macros
-
- [change_begin]
- X3J13 voted in June 1989 (DEFINE-COMPILER-MACRO) to add a facility for
- defining compiler macros that take effect only when compiling code, not when
- interpreting it.
-
- The purpose of this facility is to permit selective source-code transformations
- only when the compiler is processing the code. When the compiler is about to
- compile a non-atomic form, it first calls compiler-macroexpand-1 repeatedly
- until there is no more expansion (there might not be any to begin with). Then
- it continues its remaining processing, which may include calling macroexpand-1
- and so on.
-
- The compiler is required to expand compiler macros. It is unspecified whether
- the interpreter does so. The intention is that only the compiler will do so,
- but the range of possible ``compiled-only'' implementation strategies precludes
- any firm specification.
-
- [Macro]
-
- define-compiler-macro name lambda-list {declaration | doc-string}* {form}*
-
- This is just like defmacro except the definition is not stored in the symbol
- function cell of name and is not seen by macroexpand-1. It is, however, seen by
- compiler-macroexpand-1. As with defmacro, the lambda-list may include
- &environment and &whole and may include destructuring. The definition is
- global. (There is no provision for defining local compiler macros in the way
- that macrolet defines local macros.)
-
- A top-level call to define-compiler-macro in a file being compiled by
- compile-file has an effect on the compilation environment similar to that of a
- call to defmacro, except it is noticed as a compiler macro (see section 25.1).
-
- Note that compiler macro definitions do not appear in information returned by
- function-information; they are global, and their interaction with other lexical
- and global definitions can be reconstructed by compiler-macro-function. It is
- up to code-walking programs to decide whether to invoke compiler macro
- expansion.
-
- X3J13 voted in March 1988 (FLET-IMPLICIT-BLOCK) to specify that the body of
- the expander function defined by defmacro is implicitly enclosed in a block
- construct whose name is the same as the name of the defined macro; presumably
- this applies also to define-compiler-macro. Therefore return-from may be used
- to exit from the function.
-
- [Function]
- compiler-macro-function name &optional env
-
- The name must be a symbol. If it has been defined as a compiler macro, then
- compiler-macro-function returns the macro expansion function; otherwise it
- returns nil. The lexical environment env may override any global definition for
- name by defining a local function or local macro (such as by flet, labels, or
- macrolet) in which case nil is returned.
-
- setf may be used with compiler-macro-function to install a function as the
- expansion function for the compiler macro name, in the same manner as for
- macro-function. Storing the value nil removes any existing compiler macro
- definition. As with macro-function, a non-nil stored value must be a function
- of two arguments, the entire macro call and the environment. The second
- argument to compiler-macro-function must be omitted when it is used with setf.
-
- [Function]
- compiler-macroexpand form &optional env
- compiler-macroexpand-1 form &optional env
-
- These are just like macroexpand and macroexpand-1 except that the expander
- function is obtained as if by a call to compiler-macro-function on the car of
- the form rather than by a call to macro-function. Note that
- compiler-macroexpand performs repeated expansion but compiler-macroexpand-1
- performs at most one expansion. Two values are returned, the expansion (or the
- original form) and a value that is true if any expansion occurred and nil
- otherwise.
-
- There are three cases where no expansion happens:
-
- * There is no compiler macro definition for the car of form.
- * There is such a definition but there is also a notinline declaration,
- either globally or in the lexical environment env.
- * A global compiler macro definition is shadowed by a local function or
- macro definition (such as by flet, labels, or macrolet).
-
- Note that if there is no expansion, the original form is returned as the first
- value, and nil as the second value.
-
- Any macro expansion performed by the function compiler-macroexpand or by the
- function compiler-macroexpand-1 is carried out by calling the function that is
- the value of *macroexpand-hook*.
-
- A compiler macro may decline to provide any expansion merely by returning the
- original form. This is useful when using the facility to put ``compiler
- optimizers'' on various function names. For example, here is a compiler macro
- that ``optimizes'' (one would hope) the zero-argument and one-argument cases of
- a function called plus:
-
- (define-compiler-macro plus (&whole form &rest args)
- (case (length args)
- (0 0)
- (1 (car args))
- (t form)))
-
- [change_end]
-
- -------------------------------------------------------------------------------
-
- 8.5. Environments
-
- [change_begin]
- X3J13 voted in June 1989 (SYNTACTIC-ENVIRONMENT-ACCESS) to add some
- facilities for obtaining information from environment objects of the kind
- received as arguments by macro expansion functions, *macroexpand-hook*
- functions, and *evalhook* functions. There is a minimal set of accessors
- (variable-information, function-information, and declaration-information) and a
- constructor (augment-environment) for environments.
-
- All of the standard declaration specifiers, with the exception of special, can
- be defined fairly easily using define-declaration. It also seems to be able to
- handle most extended declarations.
-
- The function parse-macro is provided so that users don't have to write their
- own code to destructure macro arguments. This function is not entirely
- necessary since X3J13 voted in March 1989 (DESTRUCTURING-BIND) to add
- destructuring-bind to the language. However, parse-macro is worth having
- anyway, since any program-analyzing program is going to need to define it, and
- the implementation isn't completely trivial even with destructuring-bind to
- build upon.
-
- The function enclose allows expander functions to be defined in a non-null
- lexical environment, as required by the vote of X3J13 in March 1989
- (DEFINING-MACROS-NON-TOP-LEVEL) . It also provides a mechanism by which a
- program processing the body of an (eval-when (:compile-toplevel) ...) form can
- execute it in the enclosing environment (see issue (EVAL-WHEN-NON-TOP-LEVEL)
- ).
-
- In all of these functions the argument named env is an environment object. (It
- is not required that implementations provide a distinguished representation for
- such objects.) Optional env arguments default to nil, which represents the
- local null lexical environment (containing only global definitions and
- proclamations that are present in the run-time environment). All of these
- functions should signal an error of type type-error if the value of an
- environment argument is not a syntactic environment object.
-
- The accessor functions variable-information, function-information, and
- declaration-information retrieve information about declarations that are in
- effect in the environment. Since implementations are permitted to ignore
- declarations (except for special declarations and optimize safety declarations
- if they ever compile unsafe code), these accessors are required only to return
- information about declarations that were explicitly added to the environment
- using augment-environment. They might also return information about
- declarations recognized and added to the environment by the interpreter or the
- compiler, but that is at the discretion of the implementor. Implementations are
- also permitted to canonicalize declarations, so the information returned by the
- accessors might not be identical to the information that was passed to
- augment-environment.
-
- [Function]
- variable-information variable &optional env
-
- This function returns information about the interpretation of the symbol
- variable when it appears as a variable within the lexical environment env.
- Three values are returned.
-
- The first value indicates the type of definition or binding for variable in
- env:
-
- nil There is no apparent definition or binding for variable.
-
- :special
- The variable refers to a special variable, either declared or proclaimed.
-
- :lexical
- The variable refers to a lexical variable.
-
- :symbol-macro
- The variable refers to a symbol-macrolet binding.
-
- :constant
- Either the variable refers to a named constant defined by defconstant or
- the variable is a keyword symbol.
-
- The second value indicates whether there is a local binding of the name. If the
- name is locally bound, the second value is true; otherwise, the second value is
- nil.
-
- The third value is an a-list containing information about declarations that
- apply to the apparent binding of the variable. The keys in the a-list are
- symbols that name declaration specifiers, and the format of the corresponding
- value in the cdr of each pair depends on the particular declaration name
- involved. The standard declaration names that might appear as keys in this
- a-list are:
-
- dynamic-extent
- A non-nil value indicates that the variable has been declared
- dynamic-extent. If the value is nil, the pair might be omitted.
-
- ignore
- A non-nil value indicates that the variable has been declared ignore. If
- the value is nil, the pair might be omitted.
-
- type
- The value is a type specifier associated with the variable by a type
- declaration or an abbreviated declaration such as (fixnum variable). If no
- explicit association exists, either by proclaim or declare, then the type
- specifier is t. It is permissible for implementations to use a type
- specifier that is equivalent to or a supertype of the one appearing in the
- original declaration. If the value is t, the pair might be omitted.
-
- If an implementation supports additional declaration specifiers that apply to
- variable bindings, those declaration names might also appear in the a-list.
- However, the corresponding key must not be a symbol that is external in any
- package defined in the standard or that is otherwise accessible in the
- common-lisp-user package.
-
- The a-list might contain multiple entries for a given key. The consequences of
- destructively modifying the list structure of this a-list or its elements
- (except for values that appear in the a-list as a result of define-declaration)
- are undefined.
-
- Note that the global binding might differ from the local one and can be
- retrieved by calling variable-information with a null lexical environment.
-
- [Function]
- function-information function &optional env
-
- This function returns information about the interpretation of the function-name
- function when it appears in a functional position within lexical environment
- env. Three values are returned.
-
- The first value indicates the type of definition or binding of the
- function-name which is apparent in env:
-
- nil There is no apparent definition for function.
-
- :function
- The function refers to a function.
-
- :macro
- The function refers to a macro.
-
- :special-form
- The function refers to a special form.
-
- Some function-names can refer to both a global macro and a global special form.
- In such a case the macro takes precedence and :macro is returned as the first
- value.
-
- The second value specifies whether the definition is local or global. If local,
- the second value is true; it is nil when the definition is global.
-
- The third value is an a-list containing information about declarations that
- apply to the apparent binding of the function. The keys in the a-list are
- symbols that name declaration specifiers, and the format of the corresponding
- values in the cdr of each pair depends on the particular declaration name
- involved. The standard declaration names that might appear as keys in this
- a-list are:
-
- dynamic-extent
- A non-nil value indicates that the function has been declared
- dynamic-extent. If the value is nil, the pair might be omitted.
-
- inline
- The value is one of the symbols inline, notinline, or nil to indicate
- whether the function-name has been declared inline, declared notinline, or
- neither, respectively. If the value is nil, the pair might be omitted.
-
- ftype
- The value is the type specifier associated with the function-name in the
- environment, or the symbol function if there is no functional type
- declaration or proclamation associated with the function-name. This value
- might not include all the apparent ftype declarations for the
- function-name. It is permissible for implementations to use a type
- specifier that is equivalent to or a supertype of the one that appeared in
- the original declaration. If the value is function, the pair might be
- omitted.
-
- If an implementation supports additional declaration specifiers that apply to
- function bindings, those declaration names might also appear in the a-list.
- However, the corresponding key must not be a symbol that is external in any
- package defined in the standard or that is otherwise accessible in the
- common-lisp-user package.
-
- The a-list might contain multiple entries for a given key. In this case the
- value associated with the first entry has precedence. The consequences of
- destructively modifying the list structure of this a-list or its elements
- (except for values that appear in the a-list as a result of define-declaration)
- are undefined.
-
- Note that the global binding might differ from the local one and can be
- retrieved by calling function-information with a null lexical environment.
-
- [Function]
- declaration-information decl-name &optional env
-
- This function returns information about declarations named by the symbol
- decl-name that are in force in the environment env. Only declarations that do
- not apply to function or variable bindings can be accessed with this function.
- The format of the information that is returned depends on the decl-name
- involved.
-
- It is required that this function recognize optimize and declaration as
- decl-names. The values returned for these two cases are as follows:
-
- optimize
- A single value is returned, a list whose entries are of the form (quality
- value), where quality is one of the standard optimization qualities
- (speed, safety, compilation-speed, space, debug) or some
- implementation-specific optimization quality, and value is an integer in
- the range 0 to 3 (inclusive). The returned list always contains an entry
- for each of the standard qualities and for each of the
- implementation-specific qualities. In the absence of any previous
- declarations, the associated values are implementation-dependent. The list
- might contain multiple entries for a quality, in which case the first such
- entry specifies the current value. The consequences of destructively
- modifying this list or its elements are undefined.
-
- declaration
- A single value is returned, a list of the declaration names that have been
- proclaimed as valid through the use of the declaration proclamation. The
- consequences of destructively modifying this list or its elements are
- undefined.
-
- If an implementation is extended to recognize additional declaration specifiers
- in declare or proclaim, it is required that either the declaration-information
- function should recognize those declarations also or the implementation should
- provide a similar accessor that is specialized for that declaration specifier.
- If declaration-information is used to return the information, the corresponding
- decl-name must not be a symbol that is external in any package defined in the
- standard or that is otherwise accessible in the common-lisp-user package.
-
- [Function]
-
- augment-environment env &key :variable :symbol-macro
- :function :macro :declare
-
- This function returns a new environment containing the information present in
- env augmented with the information provided by the keyword arguments. It is
- intended to be used by program analyzers that perform a code walk.
-
- The arguments are supplied as follows.
-
- :variable
- The argument is a list of symbols that will be visible as bound variables
- in the new environment. Whether each binding is to be interpreted as
- special or lexical depends on special declarations recorded in the
- environment or provided in the :declare argument.
-
- :symbol-macro
- The argument is a list of symbol macro definitions, each of the form (name
- definition); that is, the argument is in the same format as the cadr of a
- symbol-macrolet special form. The new environment will have local
- symbol-macro bindings of each symbol to the corresponding expansion, so
- that macroexpand will be able to expand them properly. A type declaration
- in the :declare argument that refers to a name in this list implicitly
- modifies the definition associated with the name. The effect is to wrap a
- the form mentioning the type around the definition.
-
- :function
- The argument is a list of function-names that will be visible as local
- function bindings in the new environment.
-
- :macro
- The argument is a list of local macro definitions, each of the form (name
- definition). Note that the argument is not in the same format as the cadr
- of a macrolet special form. Each definition must be a function of two
- arguments (a form and an environment). The new environment will have local
- macro bindings of each name to the corresponding expander function, which
- will be returned by macro-function and used by macroexpand.
-
- :declare
- The argument is a list of declaration specifiers. Information about these
- declarations can be retrieved from the resulting environment using
- variable-information, function-information, and declaration-information.
-
- The consequences of subsequently destructively modifying the list structure of
- any of the arguments to this function are undefined.
-
- An error is signaled if any of the symbols naming a symbol macro in the
- :symbol-macro argument is also included in the :variable argument. An error is
- signaled if any symbol naming a symbol macro in the :symbol-macro argument is
- also included in a special declaration specifier in the :declare argument. An
- error is signaled if any symbol naming a macro in the :macro argument is also
- included in the :function argument. The condition type of each of these errors
- is program-error.
-
- The extent of the returned environment is the same as the extent of the
- argument environment env. The result might share structure with env but env is
- not modified.
-
- While an environment argument received by an *evalhook* function is permitted
- to be used as the environment argument to augment-environment, the consequences
- are undefined if an attempt is made to use the result of augment-environment as
- the environment argument for evalhook. The environment returned by
- augment-environment can be used only for syntactic analysis, that is, as an
- argument to the functions defined in this section and functions such as
- macroexpand.
-
- [Macro]
- define-declaration decl-name lambda-list {form}*
-
- This macro defines a handler for the named declaration. It is the mechanism by
- which augment-environment is extended to support additional declaration
- specifiers. The function defined by this macro will be called with two
- arguments, a declaration specifier whose car is decl-name and the env argument
- to augment-environment. This function must return two values. The first value
- must be one of the following keywords:
-
- :variable
- The declaration applies to variable bindings.
- :function
- The declaration applies to function bindings.
- :declare
- The declaration does not apply to bindings.
-
- If the first value is :variable or :function then the second value must be a
- list, the elements of which are lists of the form (binding-name key value). If
- the corresponding information function (either variable-information or
- function-information) is applied to the binding-name and the augmented
- environment, the a-list returned by the information function as its third value
- will contain the value under the specified key.
-
- If the first value is :declare, the second value must be a cons of the form
- (key . value). The function declaration-information will return value when
- applied to the key and the augmented environment.
-
- define-declaration causes decl-name to be proclaimed to be a declaration; it is
- as if its expansion included a call (proclaim '(declaration decl-name)). As is
- the case with standard declaration specifiers, the evaluator and compiler are
- permitted, but not required, to add information about declaration specifiers
- defined with define-declaration to the macro expansion and *evalhook*
- environments.
-
- The consequences are undefined if decl-name is a symbol that can appear as the
- car of any standard declaration specifier.
-
- The consequences are also undefined if the return value from a declaration
- handler defined with define-declaration includes a key name that is used by the
- corresponding accessor to return information about any standard declaration
- specifier. (For example, if the first return value from the handler is
- :variable, the second return value may not use the symbols dynamic-extent,
- ignore, or type as key names.)
-
- The define-declaration macro does not have any special compile-time side
- effects (see section 25.1).
-
- [Function]
- parse-macro name lambda-list body &optional env
-
- This function is used to process a macro definition in the same way as defmacro
- and macrolet. It returns a lambda-expression that accepts two arguments, a form
- and an environment. The name, lambda-list, and body arguments correspond to the
- parts of a defmacro or macrolet definition.
-
- The lambda-list argument may include &environment and &whole and may include
- destructuring. The name argument is used to enclose the body in an implicit
- block and might also be used for implementation-dependent purposes (such as
- including the name of the macro in error messages if the form does not match
- the lambda-list).
-
- [Function]
- enclose lambda-expression &optional env
-
- This function returns an object of type function that is equivalent to what
- would be obtained by evaluating `(function ,lambda-expression) in a syntactic
- environment env. The lambda-expression is permitted to reference only the parts
- of the environment argument env that are relevant only to syntactic processing,
- specifically declarations and the definitions of macros and symbol macros. The
- consequences are undefined if the lambda-expression contains any references to
- variable or function bindings that are lexically visible in env, any go to a
- tag that is lexically visible in env, or any return-from mentioning a block
- name that is lexically visible in env.
-
- [change_end]
-
- -------------------------------------------------------------------------------
-
-
-
-